#pragma once

#include <Core/Definitions.h>

#include <functional>
#include <unordered_map>

namespace MOE
{
	namespace Core
	{
		class ClassMeta;
	}

	namespace System
	{

		// A class that stores class name -> ClassMeta mappings.
		// User of this system may query class meta registered under this system.
		//
		// A ClassLibrary is able to import ClassMeta from other libraries.
		// The imported ClassMeta objects' lifetimes are managed by their original library.
		// On contrast, any new ClassMeta added to the library by AddClassMeta is managed by the library.
		class ClassLibrary
		{
		public:
			// Constructs an empty class library.
			ClassLibrary();

			// Constructs a class library by importing all existing class metas from another library.
			explicit ClassLibrary(const ClassLibrary& other);

			// Destructs the class library. Non-imported class meta will be destroyed.
			~ClassLibrary();

			// Add a new class meta.
			// If the new class meta has duplicated name as any existing class meta, this call will be ignored.
			void AddClassMeta(const Core::ClassMeta* classMeta);

			// Remove a class meta.
			// If the class meta is not imported from another library, it'll be destroyed.
			void RemoveClassMeta(const Core::char8* className);

			// Get a class meta with this given name.
			const Core::ClassMeta& GetClassMeta(const Core::char8* className) const;

			// Get the number of class metas.
			Core::tSize GetClassMetaCount() const;

			// Iterate over all class meta.
			void ForEachClassMeta(const std::function<void(const Core::ClassMeta&)>& func) const;

		private:
			// Import classes from another class library.
			// Only used when constructed... for now.
			void ImportFrom(const ClassLibrary& other);

		private:
			// Stores each class meta entry.
			// Additional information can be added to this structure.
			struct ClassMetaInfo
			{
				const Core::ClassMeta* mClassMeta;
				bool mIsImported;
			};

			typedef std::unordered_map<Core::tHashValue, ClassMetaInfo> tMetaMap;

			// List of all class metas.
			tMetaMap mClassMetas;
		};

	}
}
